#include "stdafx.h"
#include "httpconnection.h"

#include <curl/curl.h>

#include <format>

class HttpConnection::Private
{
public:
    Private(HttpConnection &owner)
        : o(owner)
    {
        curl_global_init(CURL_GLOBAL_ALL);
        curl_handle = curl_easy_init();
    }

    ~Private()
    {
        curl_easy_cleanup(curl_handle);
    }

    inline bool Post(const std::string &url, const std::string &data, std::string &response)
    {
        if(!curl_handle) {
            return false;
        }

        // set params
        // set curl header
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "accept: application/json");
        headers = curl_slist_append(headers, std::format("AUTHORIZATION: {0}", api_key).c_str());
        //headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "Content-Type:application/json; charset = UTF-8");
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);

        curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
        curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, &WriteCallback);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &response);

        CURLcode res = curl_easy_perform(curl_handle);
        return (res == CURLE_OK);
    }

    inline bool Get(const std::string &url, std::string &response)
    {
        if(!curl_handle) {
            return false;
        }
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "accept: application/json");
        headers = curl_slist_append(headers, std::format("AUTHORIZATION: {0}", api_key).c_str());
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);

        curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, &WriteCallback);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &response);
        curl_easy_setopt(curl_handle, CURLOPT_POST, 0L);
        curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1L);

        CURLcode res = curl_easy_perform(curl_handle);
        return (res == CURLE_OK);
    }

    static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
        size_t realsize = size * nmemb;
        std::string *str = static_cast<std::string *>(userp);
        str->append(static_cast<char *>(contents), realsize);
        return realsize;
    }

private:
    friend class HttpConnection;
    HttpConnection &o;
    CURL *curl_handle = nullptr;
    std::string api_key;
};

HttpConnection::HttpConnection()
    : p(*new Private(*this))
{}

HttpConnection::~HttpConnection()
{
    delete &p;
}

void HttpConnection::SetKey(const std::string &apiKey)
{
    p.api_key = apiKey;
}

bool HttpConnection::Post(const std::string &url, const std::string &data, std::string &response)
{
    return p.Post(url, data, response);
}

bool HttpConnection::Get(const std::string &url, std::string &response)
{
    return p.Get(url, response);
}